# -*- mode: python; -*-

import hashlib
import os
import uuid

Import("env")
Import("get_option")
Import("has_option")

if not env.TargetOSIs("windows"):
    Return()


env = env.Clone()

env.SConscript(
    must_exist=1,
    dirs=[
        "ca",
    ],
    exports=[
        "env",
    ],
)

env["WIX"] = os.environ.get("WIX")
env["WIXPATH"] = r"$WIX\bin"
env["WIXHEAT"] = r"$WIXPATH\heat.exe"
env["WIXCANDLE"] = r"$WIXPATH\candle.exe"
env["WIXLIGHT"] = r"$WIXPATH\light.exe"
env["WIXUIEXT"] = r"$WIXPATH\WixUIExtension.dll"
env["WIXUTILEXT"] = r"$WIXPATH\WixUtilExtension.dll"

if "VCREDISTMERGEMODULEPATH" not in env["MSVS"]:
    print(
        "SCons tool setup did not configure the path to the vcredist merge modules, disabling MSI installer"
    )
    Return()

sourcesList = [
    "BinaryFragment.wxs",
    "FeatureFragment.wxs",
    "LicensingFragment.wxs",
    "UIFragment.wxs",
]

# Need to do this in order to get scons to translate path separators into native format
buildDir = env.Dir("$BUILD_DIR").path
buildRoot = env.Dir("$BUILD_ROOT").path
toolBuildDir = buildDir + r"\mongo"

enterprisebase = "src\mongo\db\modules\enterprise"
enterpriseToolBuildDir = buildDir + r"\mongo\db\modules\enterprise"

# Set up parameters to pass to wix -
#
# msi_edition - "Enterprise" or "Standard"
# msi_platform - "x64" or "x86"
# msi_flavor - "2008R2Plus" or ""
#

msi_flavor = "2008R2Plus"
msi_platform = "x64"

if "enterprise" in env["MONGO_MODULES"]:  # Enterprise
    msi_edition = "Enterprise"
else:  # Community
    if get_option("ssl") == "on":
        msi_edition = "SSL"
    else:
        msi_edition = "Standard"

full_version = env["MONGO_VERSION"].partition("-")[0]

# major version is the x.y, not the x.y.z
major_version = full_version
mv = major_version.split(".")
major_version = "%s.%s" % (mv[0], mv[1])

# We must regenerate upgrade codes for each major release. These upgrade codes must also be
# different for each MSI edition.
m = hashlib.sha256()
hash_str = "{}_{}".format(major_version, msi_edition)
m.update(hash_str.encode())
upgrade_code = str(uuid.UUID(bytes=m.digest()[0:16]))

sourcesList.append("Installer_64.wxs")

sources = ["wxs/" + file for file in sourcesList]
objects = ["$BUILD_DIR/msi/" + file.replace(".wxs", ".wixobj") for file in sourcesList]

# Currently, we are planning to key the same upgrade code for each
# (msi_edition, msi_platform, msi_flavor) combination
# and change MSI ProductId on minor updates, 2.6.0 -> 2.6.1, we let Wix do automatic
# GUID generation for us rather then build a database of GUIDs in our build system
# For major updates, we are going to create a new directory/productid/upgrade_code ie, 2.6 -> 3.0

# candle: compile .wxs files into .wixobjs
candle_targets = env.Command(
    target=objects,
    source=sources,
    action=[
        '"$WIXCANDLE" -wx'
        # cannot have anything other than x.x.x.x in version string.
        # we should choose a fourth version number that reflects pre-ness.
        " -dMongoDBMajorVersion="
        + major_version
        + " -dMongoDBVersion="
        + full_version
        + " -dLicenseSource=distsrc"
        r" -dEnterpriseBase=" + enterprisebase + "\\"
        " -dBinarySource="
        + '"$DESTDIR\\$PREFIX_BINDIR"'
        + " -dMergeModulesBasePath="
        + "\"${MSVS['VCREDISTMERGEMODULEPATH']}\""
        + " -dMergeModuleFileCRT="
        + env.GetMergeModuleNameForFeature("CRT")
        + " -dEdition="
        + msi_edition
        + ' -d"ProductId=*"'
        " -dUpgradeCode="
        + upgrade_code
        + " -dCustomActionDll="
        + '"$DESTDIR\\$PREFIX_BINDIR\\mongoca.dll"'
        + " -dConfiguration=Release"
        " -dOutDir=" + buildDir + r"\msi"
        " -dPlatform="
        + msi_platform
        + " -dFlavor="
        + msi_flavor
        + r" -dProjectDir=buildscripts\packaging\msi\\"
        " -dProjectName=MongoDB"
        " -dTargetDir=" + buildDir + r"\msi"
        " -dTargetExt=.msi"
        " -dTargetFileName=${SERVER_ARCHIVE}"
        r" -dSaslSource=" + buildRoot + r"\sasl_2_1_28\bin"
        r" -dSslSource=" + env["WINDOWS_OPENSSL_BIN"] + " -out " + buildDir + r"\msi\\"
        " -arch " + msi_platform + ' -ext "$WIXUIEXT"'
        ' -ext "$WIXUTILEXT"'
        " $SOURCES"
    ],
)

pre_msi = env.Command(
    target="$BUILD_DIR/msi/${SERVER_DIST_BASENAME}.pre.msi",
    source=candle_targets,
    action=[
        '"$WIXLIGHT" -out ${TARGET} -wx -cultures:null'
        # Suppress VC140_CRT_CRT.MSM Internal Consistency Errors
        # ICE82 - Suppress "duplicate sequence number"
        # -- https://msdn.microsoft.com/en-us/library/windows/desktop/aa368798(v=vs.85).aspx
        " -sice:ICE82"
        # ICE03 - Supress "String overflow"
        # -- https://msdn.microsoft.com/en-us/library/windows/desktop/aa369037(v=vs.85).aspx
        " -sice:ICE03"
        # ICE30 - Suppress "different components install same file"
        # -- mongod.exe is installed in two different components but only one is ever used during an install
        #    so this consistency check can be ignored.
        # -- https://msdn.microsoft.com/en-us/library/windows/desktop/aa368954(v=vs.85).aspx
        " -sice:ICE30"
        ' -ext "$WIXUIEXT"'
        ' -ext "$WIXUTILEXT"'
        " ${SOURCES}"
    ],
)

env.Depends(
    pre_msi,
    [
        "#/buildscripts/packaging/msi/mongod.yaml",
        # This could potentially be a superset of what we actually
        # require to build the MSI, but it should never be a subset.
        env.Alias("install-dist"),
        # We also need the mongoca DLL.
        env.Alias("install-msi-util"),
    ],
)

env.NoCache(pre_msi)

msi = env.Command(
    target="$BUILD_DIR/msi/${SERVER_DIST_BASENAME}.msi",
    source=pre_msi,
    action=[r"$PYTHON buildscripts\msitrim.py ${SOURCES} ${TARGET}"],
)
env.AlwaysBuild(msi)
env.NoCache(msi)

env.Alias("msi", msi)
